import { Button } from "../button";
import Icon from "../icon";
import { t } from "../locale";
import transfer from "../directives/transfer";
import { measureScrollBar } from "../utils/element";
import { Close } from "kui-icons";

let cacheBodyOverflow = {};

import { withInstall } from '../utils/vue'
const Drawer = {
  name: "Drawer",
  directives: { transfer },
  props: {
    value: Boolean,
    title: { default: "Title", type: String },
    width: { default: 520, type: [Number, String] },
    height: { default: 256, type: [Number, String] },
    okText: String,
    cancelText: String,
    placement: { type: String, default: "right" },
    closable: { type: Boolean, default: true },
    footer: { type: Boolean, default: true },
    maskClosable: { type: Boolean, default: false },
    target: { type: Function, default: () => document.body },
    mask: { type: Boolean, default: true },
    loading: { type: Boolean, default: false },
  },
  watch: {
    value(v) {
      this.rendered = true;
      this.$nextTick(() => {
        this.visible = v;
        this.openHandle();
        this.resetBodyStyle(v);
      });
    },
  },
  data() {
    return {
      visible: this.value,
      rendered: this.value,
      open: this.value,
    };
  },
  beforeDestroy() {
    this.resetBodyStyle(false);
  },
  methods: {
    ok() {
      this.$emit("ok");
    },
    onKeyUp(e) {
      if (this.visible) {
        if (e.keyCode == 27) this.close();
      }
    },
    cancel() {
      this.$emit("cancel");
      this.close();
    },
    openHandle() {
      if (this.visible) {
        this.open = true;
      } else {
        setTimeout(() => {
          this.open = false;
        }, 300);
      }
    },
    close() {
      this.visible = false;
      this.$emit("input", false);
      this.$emit("cancel");
      this.$emit("close");
      this.openHandle();
    },
    maskToClose() {
      if (this.maskClosable) {
        this.close();
      }
    },
    resetBodyStyle(opened) {
      let target = this.target();
      if (opened && !Object.prototype.hasOwnProperty.call(cacheBodyOverflow, "overflow")) {
        cacheBodyOverflow = {
          width: target.style.width,
          overflow: target.style.overflow,
          overflowX: target.style.overflowX,
          overflowY: target.style.overflowY,
        };
      }
      if (opened) {
        let barWidth = measureScrollBar(true);
        let el = target == document.body ? document.documentElement : target;
        let hasBar = el.scrollHeight > el.clientHeight || el.offsetHeight > el.clientHeight;
        if (barWidth && hasBar) {
          target.style.width = `calc(100% - ${barWidth}px)`;
          target.style.overflowY = `hidden`;
        }
      } else {
        setTimeout(() => {
          Object.keys(cacheBodyOverflow).forEach((key) => {
            target.style[key] = cacheBodyOverflow[key] || "";
            delete cacheBodyOverflow[key];
          });
        }, 300);
      }
    },
  },
  render() {
    if (typeof window === "undefined") return null;
    const { title, visible, cancelText, okText, ok, placement, cancel, $slots, width, height, open, closable, close, loading } = this;
    const hasFooter = this.footer || $slots.footer;
    const cancelBtn = <Button onClick={cancel}>{cancelText || t("k.drawer.cancel")}</Button>;
    const okBtn = (
      <Button type="primary" onClick={ok} loading={loading}>
        {okText || t("k.drawer.ok")}
      </Button>
    );
    const footNode = hasFooter ? (
      <div class="k-drawer-footer">
        {$slots.footer}
        {!$slots.footer && [cancelBtn, okBtn]}
      </div>
    ) : null;
    const closeNode = closable ? (
      <span class="k-drawer-close" onClick={close}>
        <Icon type={Close} />
      </span>
    ) : null;
    const transitionName = `k-drawer-${placement}`;
    const target = this.target();
    const isBody = target == document.body;
    const classes = ["k-drawer", `k-drawer-${placement}`, { "k-drawer-open": open }, { "k-drawer-has-footer": hasFooter }, { "k-drawer-nobody": !isBody }, { "k-drawer-nomask": !this.mask }];
    let styles = {};
    if (placement == "left" || placement == "right") styles.width = /%/.test(width) ? width : width + "px";
    if (placement == "top" || placement == "bottom") styles.height = /%/.test(height) ? height : height + "px";
    // const wrapCls =
    let maskNode = null;
    if (this.mask) {
      maskNode = (
        <transition name="k-drawer-fade">
          <div class={["k-drawer-mask", { "k-drawer-mask-nobody": !isBody }]} v-show={visible} onClick={this.maskToClose}></div>
        </transition>
      );
    }
    return this.rendered ? (
      <div class={classes} v-transfer={target}>
        {maskNode}
        <transition name={transitionName}>
          <div class="k-drawer-box" v-show={visible} style={styles}>
            <div class="k-drawer-content">
              <div class="k-drawer-header">
                {closeNode}
                <div class="k-drawer-header-inner">{title}</div>
              </div>
              <div class="k-drawer-body">{$slots.default}</div>
              {footNode}
            </div>
          </div>
        </transition>
      </div>
    ) : null;
  },
};

export default withInstall(Drawer);
